import './style.scss'
import people from './assets/peopo.png'
import boss from './assets/boss.png'
import { ShootGame } from './shootGame'
import { LolGame } from './lolGame'

const btnMap = [
  { name: '贝塞尔曲线', fn: 'drawBezier' },
  { name: '时钟', fn: 'drawClock' },
  { name: '练习旋转', fn: 'drawRotate' },
  { name: '射击游戏', fn: 'startShootGame' },
  { name: '走位游戏', fn: 'lolGame' },
]

class CanvasDraws {
  constructor ({  }) {
    this.ctx2d = null
    this.canvas = null
    this.canvasId = 'canvas' + Math.ceil(Math.random() * 10000)
  }

  /**
   * 创建btn
   * @param {CanvasDraws} _this
   */
  createBtn = (_this) => {
    const fragment = document.createDocumentFragment()
    const div = document.createElement('div')
    btnMap.forEach(i => {
      const btn = document.createElement('button')
      btn.innerText = i.name
      btn.addEventListener('click', this[i.fn].bind(_this, null))
      fragment.appendChild(btn)
    })
    div.appendChild(fragment)
    div.classList.add('btns')
    document.body.appendChild(div)
  }

  /**
   * 创建画布
   */
  createCavans = () => {
    const cavans = document.createElement('canvas')
    cavans.height = document.body.clientHeight
    cavans.width = document.body.clientWidth
    cavans.innerText = ` 抱歉，你的浏览器不支持 canvas 元素
    （这些内容将会在不支持&lt;canvas%gt;元素的浏览器或是禁用了 JavaScript
    的浏览器内渲染并展现）`
    cavans.id = this.canvasId
    document.body.appendChild(cavans)
    this.ctx2d = document.querySelector(`#${this.canvasId}`).getContext('2d')
    this.canvas = document.querySelector(`#${this.canvasId}`)
  }
  /**
   * 重置画布
   */
  resetCanvas () {
    this.ctx2d.clearRect(0, 0, this.canvas.width, this.canvas.height);
  }

  /**
   * 二贝塞尔曲线
   */
  drawBezier () {
    var t = 0; // 参数 t，用于在二次贝塞尔曲线上从起点到终点进行插值计算
    // 曲线起点
    let startX = 50
    let startY = 100
    // 曲线控制点1
    let curveX = 300
    let curveY = 100
    // 曲线结束点
    let endX = 300
    let entY = 400
    // 矩形的 x 坐标，初始值为起点 x 坐标
    var rectX = startX;
    // 矩形的 y 坐标，初始值为起点 y 坐标
    var rectY = startY;

    const drawOher = () => {
      // 绘制曲线
      this.ctx2d.beginPath()
      this.ctx2d.moveTo(startX, startY)
      this.ctx2d.quadraticCurveTo(curveX, curveY, endX, entY)
      this.ctx2d.stroke()

      // 绘制连接线
      this.ctx2d.beginPath()
      this.ctx2d.strokeStyle = 'red'
      this.ctx2d.moveTo(startX, startY)
      this.ctx2d.lineTo(curveX, curveY)
      this.ctx2d.moveTo(curveX, curveY)
      this.ctx2d.lineTo(endX, entY)
      this.ctx2d.stroke()

      // 绘制控制点
      this.ctx2d.beginPath()
      this.ctx2d.rect(startX, startY, 10, 10)
      this.ctx2d.rect(curveX, curveY, 10, 10)
      this.ctx2d.rect(endX, entY, 10, 10)
      this.ctx2d.fill()
    }

    const draw = () => {
      this.resetCanvas()

      drawOher()
      // 画一个矩形
      this.ctx2d.fillStyle = 'pink'
      this.ctx2d.fillRect(rectX, rectY, 50, 50);

      // 计算当前 t 对应的坐标
      var currentPoint = getPointOnQuadraticCurve(startX, startY, curveX, curveY, endX, entY, t);

      // 更新矩形位置
      rectX = currentPoint.x - 50 / 2;
      rectY = currentPoint.y - 50 / 2;

      t += 0.02;

      if (t <= 1) {
        requestAnimationFrame(draw);
      } else {
        lateralJump()
      }
    }

    let maxY = 0
    let maxY2 = 0
    let endFlag = false
    const lateralJump = () => {
      this.resetCanvas()

      drawOher()

      if (maxY < 100) {
        maxY += 8
        maxY2 = maxY
        rectY = rectY - 8
      } else {
        maxY2 -= 10
        rectY = rectY + 10
        if (maxY2 <= 0) endFlag = true
      }

      this.ctx2d.fillStyle = 'pink'
      this.ctx2d.fillRect(rectX, rectY, 50, 50);

      if (!endFlag) {
        requestAnimationFrame(lateralJump)
      } else {
        console.log('又结束了')
      }
    }

    // 关键函数, 根据二次贝塞尔曲线参数方程计算当前 t 对应的点的坐标
    function getPointOnQuadraticCurve(startX, startY, controlX, curveY, endX, entY, t) {
      var x = Math.pow(1 - t, 2) * startX + 2 * (1 - t) * t * controlX + Math.pow(t, 2) * endX;
      var y = Math.pow(1 - t, 2) * startY + 2 * (1 - t) * t * curveY + Math.pow(t, 2) * entY;

      return { x: x, y: y };
    }
    draw()
  }

  /**
   * 时钟特效
   */
  drawClock () {
    this.resetCanvas()

    const x = this.getCentetCoordinate().x
    const y = this.getCentetCoordinate().y
    this.resetCanvas()
    const arcR = 100

    /**
     * 时钟圆
     */
    const drawArc = () => {
      const gradient = this.ctx2d.createLinearGradient(0, 0, 0, this.canvas.height);
      gradient.addColorStop(0, 'rgba(27,160,254,1)');
      gradient.addColorStop(1, 'rgba(245,245,245,1)');

      this.ctx2d.fillStyle = gradient;
      this.ctx2d.fillRect(0, 0, this.canvas.width, this.canvas.height);
    }

    /**
     * 绘制刻度
     */
    const drawLine = () => {
      for (let i = 0; i < 60; i++){
        this.ctx2d.save();
        this.ctx2d.translate(x, y);
        this.ctx2d.rotate(((Math.PI * 2) / 60) * i)
        this.ctx2d.beginPath();
        this.ctx2d.moveTo(arcR - (i % 5 ? 15 : 21), 0);
        this.ctx2d.lineTo(arcR - 5, 0);
        this.ctx2d.lineWidth = i % 5 ? 2 : 4;
        this.ctx2d.strokeStyle = i % 5 ? "rgba(255, 255, 255, 0.3)" : "rgba(255, 255, 255)";
        this.ctx2d.stroke();
        this.ctx2d.closePath();
        this.ctx2d.restore();
      }
    }


    const drawPointer = ({ x: pointerX, color, deg, width }) => {
      this.ctx2d.save()
      //设置原点
      this.ctx2d.translate(x, y);
      // 旋转指针
      this.ctx2d.rotate(deg)
      // 创建指针
      this.ctx2d.beginPath()
      this.ctx2d.moveTo(-10, 0)
      this.ctx2d.lineTo(pointerX, 0)
      this.ctx2d.lineWidth = width
      this.ctx2d.lineCap = "round"
      this.ctx2d.strokeStyle = color
      this.ctx2d.stroke()
      this.ctx2d.closePath()
      this.ctx2d.restore()
    }

    const timeing = () => {
      this.resetCanvas()
      drawArc()
      drawLine()
      // 将Math.PI * 2 ~ 360度, 根据60秒转换，每秒对应多少度，然后乘当前秒， 在减去欠的秒（欠的秒是初始值在什么角度，初始值不是正好指向12位置的）, 下面时分秒都是一个道理
      const s = (Math.PI * 2 / 60 * new Date().getSeconds()) - (Math.PI * 2 / 60 * 15)
      const m = (Math.PI * 2 / 60 * new Date().getMinutes()) - (Math.PI * 2 / 60 * 15)
      const h = (Math.PI * 2 / 12 * new Date().getHours()) - (Math.PI * 2 / 12 * 3)
      drawPointer({ x: 35, color: '#fff', deg: h, width: 6 })
      drawPointer({ x: 55, color: '#fff', deg: m, width: 4 })
      drawPointer({ x: 70, color: 'red', deg: s, width: 1 })
      requestAnimationFrame(timeing)
    }

    const runPointer = () => {
      timeing()
    }
    runPointer()
  }

  // 获取画布坐标
  getCentetCoordinate (width) {
    return {
      x: this.canvas.width / 2,
      y: this.canvas.height / 2
    }
  }

  /**
   * 旋转练习
   */
  drawRotate () {
    this.resetCanvas()

    this.ctx2d.fillStyle = 'pink'
    this.ctx2d.fillRect(10, 10, 100, 100)

    for (let index = 0; index < 60; index++) {
      this.ctx2d.save()
      this.ctx2d.translate(this.getCentetCoordinate().x, this.getCentetCoordinate().y)
      this.ctx2d.rotate(((Math.PI * 2) / 60) * index)
      this.ctx2d.beginPath();
      this.ctx2d.moveTo(0, 0)
      this.ctx2d.lineTo(0, 100)
      this.ctx2d.lineWidth = index % 5 ? 2 : 4;
      this.ctx2d.strokeStyle = index % 5 ? "pink" : "red";
      this.ctx2d.stroke()
      this.ctx2d.closePath();
      this.ctx2d.restore()
    }

    const image = new Image()
    image.src = people
    image.onload = () => {
      this.ctx2d.save()
      this.ctx2d.translate(this.getCentetCoordinate().x, this.getCentetCoordinate().y)
      // 翻转, 沿着x轴
      this.ctx2d.scale(-1, 1)
      // this.ctx2d.rotate(Math.PI)
      this.ctx2d.drawImage(image, 0, 32, 30, 30, 0, 0, 52, 60)
      this.ctx2d.restore()
    }
  }

  startShootGame () {
    new ShootGame({ ctx: this.ctx2d, canvas: this.canvas })
  }
  lolGame () {
    new LolGame({ ctx: this.ctx2d, canvas: this.canvas })
  }
}

const cavans = new CanvasDraws({})
cavans.createCavans()
cavans.createBtn(cavans)
